package com.g2room.myuall.grap.univ;

import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.g2room.myuall.grap.univ.po.ArtiCategoryPo;
import com.g2room.myuall.grap.univ.po.Article;
import com.g2room.myuall.util.DbUtil;
import com.g2room.myuall.util.HtmlUtil;
import com.g2room.myuall.util.IpUtil;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;

public class TimeGrapUnivAtic implements Runnable {
	static String grapTime = getLastGrapTime();
	public String baseUrl = "http://gaokao.eol.cn";
	static Map<String, String> categoryMap = new HashMap<String, String>();
	static Map<String, String> urlMap = new HashMap<String, String>();
	static Connection connection = null;
	
	static Map<String, ArtiCategoryPo> acps = ArtiCategoryPo.getCategories();
	static {
		categoryMap.put("高考快讯", "高考");
		urlMap.put("高考", "http://gaokao.eol.cn/news/");
		// ---------------- 以下属于报考志愿 
		// http://gaokao.eol.cn/zhiyuan/tianbao/
		categoryMap.put("志愿填报", "高考");
		urlMap.put("志愿", "http://gaokao.eol.cn/zhiyuan/tianbao/");
		// http://gaokao.eol.cn/zhiyuan/zhinan/
		categoryMap.put("报考指南", "高考");
		urlMap.put("报考", "http://gaokao.eol.cn/zhiyuan/zhinan/");
		// http://gaokao.eol.cn/zhiyuan/fenshuxian/
		categoryMap.put("历年分数线", "高考");
		urlMap.put("分数线", "http://gaokao.eol.cn/zhiyuan/fenshuxian/");
		
		// ---------------- 以下为大纲解读
		categoryMap.put("各地动态", "高考");
		urlMap.put("地方", "http://gaokao.eol.cn/gkdg/gedi/");
		
		// ---------------- 以下为专业资讯
		// http://zhuanye.eol.cn/jiedu/
		categoryMap.put("专业解读", "高考");
		urlMap.put("解读", "http://zhuanye.eol.cn/jiedu/");
		// ---------------- 以下为自招动态
		// http://gaokao.eol.cn/zizhu/news/
		categoryMap.put("自招动态", "高考");
		urlMap.put("自招", "http://gaokao.eol.cn/zizhu/news/");
		// http://gaokao.eol.cn/zizhu/zzzxpl/
		categoryMap.put("分析评论", "高考");
		urlMap.put("分析", "http://gaokao.eol.cn/zizhu/zzzxpl/");
		// ---------------- 以下为报名信息
		// http://gaokao.eol.cn/gkbm/bmxx/
		categoryMap.put("报名信息", "高考");
		urlMap.put("报考", "http://gaokao.eol.cn/gkbm/bmxx/");
		// ---------------- 以下为高职
		// http://gaokao.eol.cn/gaozhi/gzkx/
		categoryMap.put("招生快讯", "高考");
		urlMap.put("招生", "http://gaokao.eol.cn/gaozhi/gzkx/");
		categoryMap.put("报考指导", "高考");
		urlMap.put("报考", "http://gaokao.eol.cn/gaozhi/cjwt/");
		categoryMap.put("院校动态", "高考");
		urlMap.put("高校", "http://gaokao.eol.cn/gaozhi/zsxx/");
		
		// ---------------- 以下为保送生
		categoryMap.put("保送动态", "高考");
		urlMap.put("保送", "http://gaokao.eol.cn/baosong/news/");
		categoryMap.put("各校政策", "高考");
		urlMap.put("保送", "http://gaokao.eol.cn/baosong/zhengce/");
		
		// ---------------- 以下为特长生
		categoryMap.put("艺术特长生", "高考");
		urlMap.put("艺术生", "http://gaokao.eol.cn/ystc/ystcs/");
		categoryMap.put("体育特长生", "高考");
		urlMap.put("体育生", "http://gaokao.eol.cn/ystc/tytcs/");
		
		// ---------------- 以下为国防生
		categoryMap.put("国防生", "高考");
		urlMap.put("国防军校", "http://gaokao.eol.cn/junshi/guofang/");
		categoryMap.put("军校生", "高考");
		urlMap.put("国防军校", "http://gaokao.eol.cn/junshi/junxiao/");
		categoryMap.put("招飞快讯", "高考");
		urlMap.put("国防军校", "http://gaokao.eol.cn/zhaofei/fxxy/");
		
		// ---------------- 以下为小语种
		categoryMap.put("小语种", "高考");
		urlMap.put("小语种", "http://gaokao.eol.cn/xiaoyz/zxdt/");
		
		// ---------------- 以下为艺考
		categoryMap.put("艺考快讯", "高考");
		urlMap.put("艺考", "http://yikao.eol.cn/xinwen/");
		categoryMap.put("明星名人", "高考");
		urlMap.put("艺考", "http://yikao.eol.cn/mingxing/");
		
		// ------------- 高校集合
		// http://gaokao.eol.cn/daxue/zixun/
		categoryMap.put("高校资讯", "高考");
		urlMap.put("高校", "http://gaokao.eol.cn/daxue/zixun/");
		// http://gaokao.eol.cn/daxue/fangtan/
		categoryMap.put("招生访谈", "高考");
		urlMap.put("招生", "http://gaokao.eol.cn/daxue/fangtan/");
		// http://gaokao.eol.cn/daxue/mingdan/
		categoryMap.put("高校名单", "高考");
		urlMap.put("高校", "http://gaokao.eol.cn/daxue/mingdan/");
	}
	
	public static void main(String[] args) throws Exception{
		grapArtis();
    }
	
	public static void grapArtis() {
		DbUtil.closeConn(connection);
		// 获取连接
		connection = DbUtil.getMyuallConn();
		for(String type : urlMap.keySet()) {
			TimeGrapUnivAtic gua = new TimeGrapUnivAtic();
			gua.getPage(type, urlMap.get(type));
		}
		DbUtil.closeConn(connection);
	}
	
	private Integer getPageUrl(String url) {
		url = url.substring(url.indexOf("_PAGE_COUNT=") + 13);
		String page = url.substring(0, Math.min(2, url.indexOf("\"")));
		return Integer.valueOf(page);
	}
	
	/**
	 * 获取分页数据
	 * @param url
	 * @throws FailingHttpStatusCodeException
	 * @throws MalformedURLException
	 * @throws IOException
	 */
	public boolean getPage(String type, String url) {
		
		Document doc = null;
		try {
			doc = GenericGrap.getDocByIp(url);
		} catch (IOException e) {
//			e.printStackTrace();
			System.out.println(url);
			insert2ErrDb(url, 2);
		}
		if(doc == null) return false;
		
		Elements liEls = doc.getElementsByAttributeValue("class", "page_left").first().getElementsByTag("li");
		List<Article> artis = new ArrayList<Article>();
		for(Element el : liEls) {
			try {
				Element titleEl = el.getElementsByTag("a").first();
				String href = titleEl.attr("href");
				
				Article arti = new Article();
				arti.setTitle(titleEl.text());
				String publishTime = el.getElementsByTag("span").first().text();
				// 当日期达到上一次之后，则不再抓取
				if(publishTime.compareTo(grapTime) <= 0) {
					System.out.println(type + "，无最新数据");
					break;
				}
				arti.setPublishTime(publishTime);
				String sourceUrl = "";
				int state = 0;
				// 特殊处理
				if(href.startsWith("http")) {
					sourceUrl = href;
				} else if(href.startsWith("./")) {
					sourceUrl = url + href.replace("./", "");
				} else {
					state = 9;
					sourceUrl = baseUrl + "/" + href.replace("../", "");
				}
				arti.setSourceUrl(sourceUrl);
				arti.setTypeName(type);
				// 通过状态区分类型，本目录=0；其他目录为9
				arti.setState(state);
				artis.add(arti);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println(type + " 抓取到数据：" + artis.size());
        for(Article arti : artis) {
        	try {
				Thread.sleep(IpUtil.genRandomNum() * 10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
        	getDetail(arti);
        }
        grapTime = DbUtil.getLastDay();
        updatePublishTime(grapTime);
        return true;
	}
	
	public void getDetail(Article arti) {

		Document doc = null;
		try {
			doc = GenericGrap.getDocByIp(arti.getSourceUrl());
		} catch (IOException e) {
			System.out.println(arti.getSourceUrl());
//			e.printStackTrace();
			insert2ErrDb(arti.getSourceUrl(), 3);
		}
		if(doc == null) return;
		
		try {
			// 获取分页信息
			int pageNum = 0;
			try {
				Element pel = doc.getElementById("pagenav");
				if(null == pel) return;
				
				pageNum = getPageUrl(pel.html());
				arti.setPageNum(pageNum);
			} catch (Exception e) {
				System.out.println("242==="+arti.getSourceUrl());
//				e.printStackTrace();
			}
			
			String content = doc.getElementsByAttributeValue("class", "TRS_Editor").html();
			// 标记获取标签
			boolean flag = false;
			// 如果为空则尝试从mcontent 获取
			if(null == content || content.length() < 5) {
				content = doc.getElementById("mcontent").html();
				flag = true;
			}
			if(pageNum > 1) {
				for(int i=1; i< pageNum; i++) {
					String href = arti.getSourceUrl().replace(".shtml", "_"+i+".shtml");
					Document pageDoc = null;
					try {
						pageDoc = GenericGrap.getDocByIp(href);
					} catch (Exception e) {
//						e.printStackTrace();
						insert2ErrDb(href, 4);
						return;
					}
					if(pageDoc == null) continue;
					content += "\n"+pageDoc.getElementsByAttributeValue("class", "TRS_Editor").html();
					// 如果为空则尝试从mcontent 获取
					if(flag) {
						content += "\n"+pageDoc.getElementById("mcontent").html();
					}
				}
			}
			content = GenericMyuall.handleSpace(HtmlUtil.delAllTag(content));
			
			arti.setContent(content);
			// 获取发布时间
			insert2Db(arti);
        } catch (Exception e) {
        	e.printStackTrace();
			insert2ErrDb(arti.getSourceUrl(), 5);
        }
	}
	

	public static void insert2Db(Article article) {
		try {
			PreparedStatement ps = connection.prepareStatement("insert into ncee_arti(title,content,publish_time,type_name,source,source_url,state,category_name,page_num,type_code,category_code) values(?,?,?,?,?,?,?,?,?,?,?)");
			ps.setString(1, article.getTitle());
			ps.setString(2, article.getContent());
			ps.setString(3, article.getPublishTime());
			ps.setString(4, article.getTypeName());
			ps.setString(5, article.getSource());
			ps.setString(6, article.getSourceUrl());
			ps.setInt(7, article.getState());
			ps.setInt(9, article.getPageNum());
			
			ArtiCategoryPo acp = acps.get(article.getTypeName());
			if(null != acp) {
				ps.setString(8, acp.getCategoryName());
				ps.setString(10, acp.getTypeCode());
				ps.setString(11, acp.getCategoryCode());
			}
			ps.execute();
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public void insert2ErrDb(String url, int type) {
		try {
			PreparedStatement grapPs = connection.prepareStatement("INSERT INTO `univ_err` (`url`,type) "
					+ "values(?,?)");
			grapPs.setString(1, url);
			grapPs.setInt(2, type);
			grapPs.execute();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	public void updatePublishTime(String content) {
		try {
			PreparedStatement grapPs = connection.prepareStatement("update `univ_arti_set` set content=? where id=1 ");
			grapPs.setString(1, content);
			grapPs.execute();
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
	public static String getLastGrapTime() {
		try {
			Statement statement = connection.createStatement();
			String sql = "select * from univ_arti_set where id=1";
			ResultSet rs = statement.executeQuery(sql);
			while(rs.next()) {
				grapTime = rs.getString("content");
			}
			rs.close();
			statement.close();
		} catch(Exception e) {
			e.printStackTrace();
		}
		return grapTime;
	}

	@Override
	public void run() {
//		getNav();
	}
}
